//
//  MUPSingleton.h
//  MUPFoundation
//
//  Created by yanzw on 14-10-11.
//  Copyright (c) 2014年 nd. All rights reserved.
//

/**
 *    此文件进行单例、全局共享对象的声明与实现
 *
 *    单例：程序周期内永远只有一个对象存在，懒加载的形式产生，采用[CLASS singleton]访问
 *    @warnning 使用单例宏在实现文件中不能实现如下方法：【allocWithZone:】、【copyWithZone:】、【mutableCopyWithZone:】、【copy】、【mutableCopy】、【init】
 *    全局共享对象：非单例，仅是一个访问上线程安全的对象，除此对象之外还能主动创建其他对象，采用[CLASS sharedInstance]访问
 */

#pragma mark - 全局共享对象
#undef DEF_SHAREDINSTANCE
// 声明全局共享实例
#define DEF_SHAREDINSTANCE(...) \
+ (instancetype)sharedInstance;

#undef	IMP_SHAREDINSTANCE
// 实现全局共享实例
#define IMP_SHAREDINSTANCE(...) \
+ (instancetype)sharedInstance { \
    static dispatch_once_t once; \
    static id __singleton__; \
    dispatch_once( &once, ^{ __singleton__ = [[self alloc] init]; } ); \
    return __singleton__; \
}

#pragma mark - 单例
#undef	DEF_SINGLETON
//申明单例
#define DEF_SINGLETON(CLASS, functionName) \
+ (instancetype)functionName;

#undef	IMP_SINGLETON
//实现单例
#define IMP_SINGLETON(CLASS, functionName) \
\
static CLASS *SINGLETON = nil;  \
\
static bool isFirstAccess = YES;    \
\
+ (instancetype)functionName {  \
    static dispatch_once_t onceToken;   \
    dispatch_once(&onceToken, ^{    \
        isFirstAccess = NO; \
        SINGLETON = [[super allocWithZone:NULL] init];  \
    }); \
    \
    return SINGLETON;   \
}   \
\
+ (id) allocWithZone:(NSZone *)zone {   \
    return [self functionName];   \
}   \
\
+ (id)copyWithZone:(struct _NSZone *)zone { \
    return [self functionName];   \
}   \
\
+ (id)mutableCopyWithZone:(struct _NSZone *)zone {  \
    return [self functionName];   \
}   \
\
- (id)copy {    \
    return [[CLASS alloc] init];    \
}   \
\
- (id)mutableCopy { \
    return [[CLASS alloc] init];    \
}   \
\
- (id) init {   \
    if(SINGLETON){  \
        return SINGLETON;   \
    }   \
    if (isFirstAccess) {    \
        [self doesNotRecognizeSelector:_cmd];   \
    }   \
    self = [super init];    \
    return self;    \
}

#pragma mark - 快速创建共享实例
#define mupDispatchAllocSingleton(instance, implement) \
static id instance = nil; \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
instance = [[implement alloc] init];\
});